
package cn.zlg.common.datadump.executor;

import cn.zlg.common.datadump.annotation.DataDumpEntity;
import cn.zlg.common.datadump.annotation.DataDumpField;
import cn.zlg.common.datadump.bean.BatchDeleteResult;
import cn.zlg.common.datadump.condition.HttpServletRequestQueryConditionBuilder;
import cn.zlg.common.datadump.condition.QueryCondtionWrapper;
import cn.zlg.common.datadump.condition.QueryFieldWithValue;
import cn.zlg.common.datadump.convertor.FieldValueConvert;
import cn.zlg.common.datadump.service.BatchDeleteService;
import cn.zlg.common.datadump.util.QueryDslUtils;
import com.mysema.commons.lang.Assert;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.ComparableExpressionBase;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.core.types.dsl.SimpleExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 批量删除
 */
@Service
@Order(9999)
public class JPABatchDeleteExecutor implements ApplicationContextAware, BatchDeleteService {

    private static final Logger logger = LoggerFactory.getLogger(JPABatchDeleteExecutor.class);

    @Autowired
    private JPAQueryFactory factory;

    private ApplicationContext applicationContext;

    public BatchDeleteResult batchDelete(Class entity, List ids) throws Exception {
        if(ids == null || ids.size()==0) {
            return new BatchDeleteResult();
        }
        DataDumpEntity entityAnnotation = (DataDumpEntity) entity.getAnnotation(DataDumpEntity.class);
        Assert.notNull(entityAnnotation,
                String.format("类%s没有%s注解,无法解析", entity.getName(), DataDumpEntity.class.getSimpleName()));
        Class mainEntity = entityAnnotation.entity();
        EntityPathBase qEntity = QueryDslUtils.findQEntityInstance(mainEntity);
        String batchDeleteField = entityAnnotation.batchDeleteField();
        String deleteFlagValue = entityAnnotation.deleteFlagValue();
        Path deleteField = QueryDslUtils.findQPath(mainEntity, batchDeleteField);
        SimpleExpression idField = (SimpleExpression)QueryDslUtils.findQPath(mainEntity, entityAnnotation.idField());
        if(deleteField == null) {
            logger.warn("{}指定的删除字段[{}]不存在，将执行物理删除", entity.getName(), batchDeleteField);
           int count = (int) factory.delete(qEntity).where(idField.in(ids)).execute();
           return createResult(ids.size(), count);
        } else {
            Object value = convertToTargetTypeValue(deleteField, deleteFlagValue);
            int count = (int) factory.update(qEntity).set(deleteField, value).where(idField.in(ids)).execute();
            return createResult(ids.size(), count);
        }
    }

    BatchDeleteResult createResult(int total, int success) {
        BatchDeleteResult r = new BatchDeleteResult();
        r.setTotal(total);
        r.setSuccess(success);
        return r;
    }

    private Object convertToTargetTypeValue(Path deleteField, String deleteFlagValue) throws ParseException {
       return HttpServletRequestQueryConditionBuilder.convertValueToType(deleteFlagValue, deleteField.getType());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

}
